package org.ewaf.framework.struts2.velocity;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.ToolboxManager;

public class VelocityUtil {

	/**
	 * 合并模板文件与Context
	 */
	public static void mergeFile(String fileName, VelocityContext ctx, OutputStream os) throws Exception {
		mergeFile(fileName, ctx, os, null, null);
	}
	
	/**
	 * 合并模板文件与Context
	 */
	public static void mergeFile(String fileName, VelocityContext ctx, 
			OutputStream os, String inputEncoding, String outputEncoding) throws Exception {
		
		if (outputEncoding == null) {
			VelocityEngine engine = VelocityManagerEx.getInstance().getVelocityEngine();
			outputEncoding = (String) engine.getProperty(VelocityEngine.OUTPUT_ENCODING);
		}
		
		OutputStreamWriter writer = new OutputStreamWriter(os, outputEncoding);
		try {
			mergeFile(fileName, ctx, writer, inputEncoding);
		} finally {
			writer.close();
		}
	}
	
	/**
	 * 合并模板文件与Context
	 * 调用者负责Writer的安全关闭
	 */
	public static void mergeFile(String fileName, VelocityContext ctx, Writer writer) throws Exception {
		mergeFile(fileName, ctx, writer, null);
	}
	
	/**
	 * 合并模板文件与Context
	 * 调用者负责Writer的安全关闭
	 */
	public static void mergeFile(String fileName, VelocityContext ctx,
			Writer writer, String inputEncoding) throws Exception {
		
		VelocityManagerEx mgr = VelocityManagerEx.getInstance();
		VelocityEngine engine = mgr.getVelocityEngine();
		
		System.out.println(engine+"engine>>>>>>>>>>>>>>>>>>>>>");
		
		ToolboxManager toolboxMgr = mgr.getToolboxManager();
		Context context = new MergedContext(ctx, toolboxMgr.getToolbox(null));
		
		if (inputEncoding != null) {
			engine.mergeTemplate(fileName, inputEncoding, context, writer);
		} else {
			engine.mergeTemplate(fileName, context, writer);
		}
	}
	
	/**
	 * 合并模板文件与Context
	 */
	public static String mergeFile(String fileName, VelocityContext ctx) throws Exception {
		return mergeFile(fileName, ctx, (String) null);
	}
	
	/**
	 * 合并模板文件与Context
	 */
	public static String mergeFile(String fileName, VelocityContext ctx, String inputEncoding) throws Exception {
		StringWriter writer = new StringWriter();
		mergeFile(fileName, ctx, writer, inputEncoding);
		return writer.toString();
	}
	
	
	/**
	 * 合并模板字符串与Context
	 * @param str 模板内容，可以包含VTL
	 */
	public static String mergeString(String str, VelocityContext ctx) throws Exception {
		VelocityManagerEx mgr = VelocityManagerEx.getInstance();
		VelocityEngine engine = mgr.getVelocityEngine();
		ToolboxManager toolboxMgr = mgr.getToolboxManager();
		Context context = new MergedContext(ctx, toolboxMgr.getToolbox(null));
		StringWriter writer = new StringWriter();
		return engine.evaluate(context, writer, "mergeString", str) ? writer.toString() : "";
	}
	
	@SuppressWarnings("unchecked")
	private static class MergedContext extends VelocityContext {
		
		private static final long serialVersionUID = -2245892648342053240L;
		
		
		private final Map toolbox;
		
		public MergedContext(VelocityContext ctx, Map toolbox) {
			super(ctx);
			this.toolbox = toolbox;
		}

		public Object internalGet(String key) {
			if (toolbox != null) {
				Object tool = toolbox.get(key);
				if (tool != null) {
					return tool;
				}
			}
			
			return super.internalGet(key);
		}
		
	}
	
}
